package com.loves.admin.util.filter;

import com.loves.admin.model.User;
import com.loves.admin.util.JwtTokenUtil;
import com.loves.admin.util.RedisUtil;
import com.loves.admin.util.common.Constant;
import com.loves.admin.util.exception.BizException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.annotation.Resource;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Map;

@Component
public class JwtAuthenticationTokenFilter extends OncePerRequestFilter {
    private Logger logger = LoggerFactory.getLogger(JwtAuthenticationTokenFilter.class);

    @Resource
    private RedisUtil redisUtil;

    @Resource
    private JwtTokenUtil jwtTokenUtil;


    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        String authHeader = request.getHeader(jwtTokenUtil.JWT_HEADER);
        response.setHeader("Content-type", "text/html;charset=UTF-8");//设置响应类型为html，编码为utf-8，处理相应页面文本显示的乱码；
        response.setCharacterEncoding("UTF-8");//如果响应类型为文本，那么就需要设置文本的编码类型，然后浏览器使用这个编码来解读文本。注意，如果没有设置contentType，那么浏览器会认为contentType为text/html，如果没设置编码，那么默认为ISO-8859-1编码。
        if (null == authHeader || !authHeader.startsWith(jwtTokenUtil.JWT_TOKEN_HEAD)){
            filterChain.doFilter(request,response);//token格式不正确
            return;
        }
        String authToken = authHeader.substring(jwtTokenUtil.JWT_TOKEN_HEAD.length());
        //获取redis中的token信息
        if (!redisUtil.hasKey(authToken)){
            //token 不存在 返回错误信息
            throw new BizException("token不存在，请重新输入！");
        }
        //获取缓存中的信息
        Map<Object,Object> hashMap = redisUtil.hmget(authToken);
        if (null == hashMap){
            //用户信息不存在或转换错误，返回错误信息
            throw new BizException("用户信息不存在！");
        }
        User user = new User();
        user.setId((String) hashMap.get("id"));
        //更新token过期时间
        redisUtil.expire(authToken, Constant.EXPIRATION_DATE);
        //将信息交给security
        UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(user,null,null);
        authenticationToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
        SecurityContextHolder.getContext().setAuthentication(authenticationToken);
        filterChain.doFilter(request,response);
    }

}
